<?php

class Engine_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract {
    
	protected $session;
	protected $auth;
	protected $_acl;
	protected $authUser;
	protected $cache;
	
	public function __construct(Array $options = array()) {
		$this->session = new Zend_Session_Namespace();;		
		$this->auth = Zend_Registry::get('WJAuth');
		$this->cache = Zend_Registry::get('Zend_Cache');
		return $this->init($options);
    }

    public function init(array $options) {   
    	$this->_acl = new Zend_Acl();
    	if ($this->auth->isActive()) {
    		$this->authUser = $this->auth->authRecord();
			$this->addRoles();    		
			$this->addResources();
			$this->addAccess();
    	}
		Zend_Registry::set('Zend_Acl', $this->_acl);
		return $this->_acl;
    }
    
    
    protected function addRoles() {
    	
    	if( ($results = $this->cache->load('acl_roles')) === false ) {
    		$acl_roles = new Engine_Db_Table_AclRoles();
    		$select = $acl_roles->select()->order('role_id');
    		$results = $acl_roles->fetchAll($select);
    		$this->cache->save($results, 'acl_roles');
    	}
    	foreach ($results as $row) {
    		$this->_acl->addRole(new Zend_Acl_Role($row['role_name']));
    	}
		
    	// SELECT authenticated users ACL Roles (not cached)
    	$acl_user_roles = new Engine_Db_Table_AclUserRoles();
    	$select = $acl_user_roles->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
    	$select->setIntegrityCheck(false);
		$select->joinLeft(ACL_ROLES, 'user_role_role_id = role_id');
		$select->where('user_role_user_id = ?', $this->authUser->user_id);
		$select->order('user_role_role_id');
    	$results = $acl_user_roles->fetchAll($select);
    	
    	// Build roles array for the authenticated user
    	$roles = array();
    	foreach($results as $row) {
    		$roles[] = $row['role_name'];
    	}
    	// 
    	$username = $this->authUser->user_username . 'ACLrole';
    	$this->authUser->aclRole = $username; 
   		$this->_acl->addRole(new Zend_Acl_Role($username), $roles); 	
    }
    
    protected function addResources() {
    	if( ($results = $this->cache->load('acl_resources')) === false ) {		
    		$acl_resources = new Engine_Db_Table_AclResources();
    		$select = $acl_resources->select();
    		$select->order('resource_id');
    		$results = $acl_resources->fetchAll($select);
       		$this->cache->save($results, 'acl_resources');
    	}
    	foreach ($results as $row) {
			$this->_acl->addResource(new Zend_Acl_Resource($row['resource_name']));
    	}    
    }
    
    protected function addAccess() {
    	if( ($results = $this->cache->load('acl_access')) === false ) {    		
    		$acl_access = new Engine_Db_Table_AclAccess();
    		$select = $acl_access->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
    		$select->setIntegrityCheck(false);
    		$select->joinLeft(ACL_RESOURCES, 'access_resource_id = resource_id');
    		$select->joinLeft(ACL_ROLES, 'access_role_id = role_id ');
    		$select->order('access_allow');
    		$select->order('access_resource_id');
    		$results = $acl_access->fetchAll($select);
    		$this->cache->save($results, 'acl_access');
    	}
    	foreach ($results as $row) {
    		if ($row['access_allow'] == false) {
    			$this->_acl->deny($row['role_name'], $row['resource_name']);
    		} else {
    			$this->_acl->allow($row['role_name'], $row['resource_name']);
    		}
    	}
    }
    
    public function routeShutdown($request) {
   		$this->secureAdminModule();
    }
    
    public function hasAuth() {
    	$result = false;
    	if (!$this->auth->isActive()) { 
								
			// Save page the user is requesting access to
			$this->session->pageRequest = $_SERVER['REQUEST_URI'];
				
			// Login required			
			$this->getResponse()->clearBody();
			$this->getResponse()->clearHeaders();
			$this->getResponse()->setRedirect(Zend_Registry::get('baseUrl').'/user/login');
		} else {
			$result = true;
		}   	
		return $result;
    }
    
    public function secureAdminModule() {
    	
    	// If Admin Module AND no Auth namespace, then reroute to Login via hasAuth
		if ($this->getRequest()->getModuleName() == 'admin') {
			if ($this->hasAuth()) {

				// User attempting to access Admin Module :: AUTHENTICATE User
				$row = $this->auth->authRecord();
				$id = $row->user_id;
					
				$module = $this->getRequest()->getModuleName();
				$controller = $this->getRequest()->getControllerName();
				$action = $this->getRequest()->getActionName();			
				$resource = $module . "/" . $controller . "/" . $action;
					
				try {
					$allowed = $this->_acl->isAllowed($this->authUser->aclRole, $resource);
				} catch (Exception $e) {
					$allowed = false;	
				}

				if (!$allowed) {
					$this->session->pageRequest = $_SERVER['REQUEST_URI'];
					$this->getResponse()->clearBody();
					$this->getResponse()->clearHeaders();
					$this->getResponse()->setRedirect(Zend_Registry::get('baseUrl').'/user/unauthorized');					
				}
			}
		}
    }

}

?>